#include "exf.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//获取exf文件信息
ExfFileInfo* Exf_LoadInfo(string file)
{
    FILE* f = _wfopen(file, T("rb"));
    if(f == null)
        return null;
    //读取基础头
    byte sih[8];
    fread(&sih, 1, 8, f);
    //验证数据
    if(sih[0] != 0XDC || sih[1] != 'E' || 
       sih[2] != 'X' || sih[3] != 'F' )
    {
        return null;
    }
    ExfFileInfo* efi = malloc(sizeof(ExfFileInfo));
    efi->filePath = file;
    efi->stream = f;
    //获取文件大小
    fseek(f, 0, SEEK_SET);
    fseek(f, 0, SEEK_END);
    efi->size = ftell(f);

    efi->flag[0] = 0XDC;
    efi->flag[1] = 'E';
    efi->flag[2] = 'X';
    efi->flag[3] = 'F';

    efi->type = sih[4];
    efi->format = sih[5];
    if(sih[6] == 0XFE)
        efi->isBig = true;
    else if(sih[6] == 0XEF)
        efi->IsBig = false;
    efi->bitFlag = sih[7];
    return efi;
}


//写出exf文件
bool Exf_Write(string file, ExfFileWrite write)
{
    FILE* f = _wfopen(file, T("wb"));
    if(f == null)
        return null;
    //写入头部
    if(write->bitFlag == 0X32)
        fwrite(write->header32, sizeof(Exf32_Header), 1, f);
    else if(write->bitFlag == 0X64)
        fwrite(write->header64, sizeof(Exf64_Header), 1, f);
    //写入扩展头
    int64 ehoffset = 0;
    if(write->ehsize > 0)
    {
        ehoffset = ftell(f);
        fwrite(write->extHeader, write->ehsize, 1, f);
    }
    //写入节表
    int64 shoffset = 0;
    if(write->shcount > 0)
    {
        shoffset = ftell(f);
        if(write->bitFlag == 0X32)
            fwrite(write->section32s, sizeof(Exf32_SectionHeader), write->shcount, f);
        else if(write->bitFlag == 0X64)
            fwrite(write->section64s, sizeof(Exf64_SectionHeader), write->shcount, f);
    }
    //写入数据
    int64 dsoffset = 0;
    if(write->dssize > 0)
    {
        dsoffset = ftell(f);
        fwrite(write->data, write->dssize, 1, f);
    }

    //重写头部
    fseek(f, 0, SEEK_SET);
    if(write->bitFlag == 0X32)
    {
        Exf32_Header* h32 = write->header32;
        h32->ident[0] = 0XDC;
        h32->ident[1] = 'E';
        h32->ident[2] = 'X';
        h32->ident[3] = 'F';
        h32->ident[4] = write->type;
        h32->ident[5] = 0X01;
        if(write->bsMarker == 0X00)
            h32->ident[6] = 0XFE;
        else
            h32->ident[6] = write->bsMarker;
        h32->ident[7] = 32;
        h32->ehoffset = ehoffset;
        h32->ehsize = write->ehsize;
        h32->shcount = write->shcount;
        h32->shoffset = shoffset;
        h32->dsoffset = dsoffset;
        h32->dssize = write->dssize;
        fwrite(h32, sizeof(Exf32_Header), 1, f);
    }
    else if(write->bitFlag == 0X64)
    {
        Exf32_Header* h64 = write->header64;
        h64->ident[0] = 0XDC;
        h64->ident[1] = 'E';
        h64->ident[2] = 'X';
        h64->ident[3] = 'F';
        h64->ident[4] = write->type;
        h64->ident[5] = 0X01;
        if(write->bsMarker == 0X00)
            h64->ident[6] = 0XFE;
        else
            h64->ident[6] = write->bsMarker;
        h64->ident[7] = 64;
        h64->ehoffset = ehoffset;
        h64->ehsize = write->ehsize;
        h64->shcount = write->shcount;
        h64->shoffset = shoffset;
        h64->dsoffset = dsoffset;
        h64->dssize = write->dssize;
        fwrite(h64, sizeof(Exf64_Header), 1, f);
    }
    return true;
}



//获取32位exf文件头
Exf32_Header *Exf32_GetHeader(ExfFileInfo* fi)
{
    fseek(fi->stream, 0, SEEK_SET);
    Exf32_Header* exfh = malloc(sizeof(Exf32_Header));
    fread(&exfh, sizeof(Exf32_Header), 1, fi->stream);
    return exfh;
}

//获取32位节头表
Exf32_SectionHeader *Exf32_GetSections(ExfFileInfo* fi, Exf32_Header* h)
{
    Exf32_SectionHeader* sections = malloc(sizeof(Exf32_SectionHeader) * h->shcount);
    fseek(fi->stream, h->shoffset, SEEK_SET);
    fread(&sections, sizeof(Exf32_SectionHeader), h->shcount, fi->stream);
    return sections;
}


//获取64位exf文件头
Exf64_Header *Exf64_GetHeader(ExfFileInfo* fi)
{
    fseek(fi->stream, 0, SEEK_SET);
    Exf64_Header* exfh = malloc(sizeof(Exf64_Header));
    fread(&exfh, sizeof(Exf64_Header), 1, fi->stream);
    return exfh;    
}

//获取64位节头表
Exf64_SectionHeader *Exf64_GetHeader(ExfFileInfo* fi, Exf64_Header* h)
{
    Exf64_SectionHeader* sections = malloc(sizeof(Exf64_SectionHeader) * h->shcount);
    fseek(fi->stream, h->shoffset, SEEK_SET);
    fread(&sections, sizeof(Exf64_SectionHeader), h->shcount, fi->stream);
    return sections;
}



